#include <iostream>
#include <conio.h>
#define SIZE 9999999
using namespace std;
int floors, moveUp, moveDown, destination;

template <class Qtype> class MyQueue {
    Qtype queue[SIZE];
    int first, last, size;

    public:

    MyQueue(){
        first = 0; last = 0; size = 0;
    }

    void enQueue(Qtype newElem){
        if(last+1 == first || (last+1 == SIZE && first == 0)){
            cout << "Error, queue is full!" << endl;
            return;}

        last++; size++;
        if(last==SIZE)
            last = 0;
        queue[last] = newElem;
    }

    Qtype deQueue(){
        if(first == last){
            cout << "You tried getting object from empty queue!" << endl;
            //return NULL; <-- replace with throw statement plx
            }

        first++; size--;
        if(first==SIZE)
            first = 0;
        return queue[first];
    }

    void deQueueLast(){
        if(first == last){
            cout << "Erranous call to dequeueLast. Bad boy!" << endl;
            return;
        }

        if(last!=0){
            last--;
            size--;}
    }

    int getSize(){ return size; }
};

class Action{
    private:
    int steps, currentFloor, movement;
    MyQueue<Action*> *theQ;

    public:
    Action(int steps_, int currentFloor_, int movement_, MyQueue<Action*> *theQ_){
        steps = steps_; currentFloor = currentFloor_; movement = movement_;
        theQ = theQ_;
    }

    Action(){
    }

    bool execute(){
        currentFloor += movement;
        if(currentFloor == destination){
            cout << steps << " moves are needed to get there!" << endl;
            return true;
        }

        if((currentFloor + moveUp) <= floors)
            theQ->enQueue(new Action(steps+1, currentFloor, moveUp, theQ));

        if((currentFloor - moveDown) >0)
            theQ->enQueue(new Action(steps+1, currentFloor, -moveDown, theQ));
        return false;
    }
};


int main(){
    MyQueue<Action*> *mq = new MyQueue<Action*>();
    int amount;

    cout << "Floors: "; cin >> floors;
    cout << "Movement up: "; cin >> moveUp;
    cout << "Movement down: "; cin >> moveDown;
    cout << "Destination floor: "; cin >> destination;

    mq->enQueue(new Action(0, 1, 0, mq));

    bool test, done=false;
    do{
        amount = mq->getSize();
//        cout << "Amount: " << amount << endl;
//        getch();
        for(int i=0; i<amount; i++){
            test = mq->deQueue()->execute();
            if (test) return 0;
        }
    }while(!done);
    delete(mq);

    return 0;
}
